package com.rui.builder.main;

import com.rui.builder.model.AsusComputerBuilder;
import com.rui.builder.model.ComputerDirector;
import com.rui.builder.model.SimpleComputerBuilder;
import com.rui.builder.model.SimpleComputerBuilder2;
import com.rui.builder.obj.Computer;

/**
 * 建造者模式（Builder）
 *
 * <p>
 * 建造者模式是将一个复杂对象的构建与它的表示分离，使得同样的构建过程可以创建不同的表示。
 * 用户只需指定需要建造的类型就可以获得对象，建造过程及细节不需要了解。
 * <p>
 * 建造者（Builder）模式包含如下角色：
 * <p>
 * 抽象建造者类（Builder）：这个接口规定要实现复杂对象的那些部分的创建，并不涉及具体的部件对象的创建。
 * 具体建造者类（ConcreteBuilder）：实现 Builder 接口，完成复杂产品的各个部件的具体创建方法。在构造过程完成后，提供产品的实例。
 * 产品类（Product）：要创建的复杂对象。
 * 指挥者类（Director）：调用具体建造者来创建复杂对象的各个部分，在指导者中不涉及具体产品的信息，只负责保证对象各部分完整创建或按某种顺序创建。
 * <p>
 * <p>
 * 适用场景：
 * 适用于创建对象需要很多步骤，但是步骤顺序不一定固定。
 * 如果一个对象有非常复杂的内部结构（属性），把复杂对象的创建和使用进行分离。
 * <p>
 * 优点：
 * 封装性好，创建和使用分离。
 * 扩展性好，建造类之间独立、一定程度上解耦。
 * <p>
 * 缺点：
 * 产生多余的Builder对象。
 * 产品内部发生变化，建造者都要修改，成本较大。
 * <p>
 * 与工厂模式的区别：
 * 建造者模式更注重方法的调用顺序，工厂模式更注重创建对象。
 * 创建对象的力度不同，建造者模式创建复杂的对象，由各种复杂的部件组成，工厂模式创建出来的都一样。
 * 关注点不同，工厂模式只需要把对象创建出来就可以了，而建造者模式中不仅要创建出这个对象，还要知道这个对象由哪些部件组成。
 * 建造者模式根据建造过程中的顺序不一样，最终的对象部件组成也不一样。
 * <p>
 * 与抽象工厂模式的区别：
 * 抽象工厂模式实现对产品族的创建，一个产品族是这样的一系列产品：具有不同分类维度的产品组合，
 * 采用抽象工厂模式则是不需要关心构建过程，只关心什么产品由什么工厂生产即可。
 * 建造者模式则是要求按照指定的蓝图建造产品，它的主要目的是通过组装零配件而产生一个新产品。
 * 建造者模式所有函数加到一起才能生成一个对象，抽象工厂一个函数生成一个对象
 *
 * @author ZhangRui
 * @date 2023/03/02 14:53
 **/
public class BuilderMain {


    public static void main(String[] args) {

        ComputerDirector computerDirector = new ComputerDirector(new AsusComputerBuilder());
        // Computer(motherboard=Extreme主板, cpu=Inter 12900KS, memory=芝奇幻峰戟 16G*2, disk=三星980Pro 2T, gpu=华硕3090Ti 水猛禽, power=雷神二代1200W, heatSink=龙神二代一体式水冷, chassis=太阳神机箱)
        System.out.println(computerDirector.construct());

        testSimpleComputer();

        testSimpleComputer2();
    }

    private static void testSimpleComputer() {
        SimpleComputerBuilder simpleComputerBuilder = new SimpleComputerBuilder();
        simpleComputerBuilder.buildMotherBoard("Extreme主板");
        simpleComputerBuilder.buildCpu("Inter 12900K");
        simpleComputerBuilder.buildMemory("芝奇幻峰戟 16G*2");
        simpleComputerBuilder.buildDisk("三星980Pro 2T");
        simpleComputerBuilder.buildGpu("华硕3090Ti 水猛禽");
        simpleComputerBuilder.buildPower("雷神二代1200W");
        simpleComputerBuilder.buildHeatSink("龙神二代一体式水冷");
        simpleComputerBuilder.buildChassis("太阳神机箱");
        // Computer(motherboard=Extreme主板, cpu=Inter 12900K, memory=芝奇幻峰戟 16G*2, disk=三星980Pro 2T, gpu=华硕3090Ti 水猛禽, power=雷神二代1200W, heatSink=龙神二代一体式水冷, chassis=太阳神机箱)
        System.out.println(simpleComputerBuilder.build());
    }

    private static void testSimpleComputer2() {

        Computer asusComputer = new SimpleComputerBuilder2().buildMotherBoard("Extreme主板")
                .buildCpu("Inter 12900K")
                .buildMemory("芝奇幻峰戟 16G*2")
                .buildDisk("三星980Pro 2T")
                .buildGpu("华硕3090Ti 水猛禽")
                .buildPower("雷神二代1200W")
                .buildHeatSink("龙神二代一体式水冷")
                .buildChassis("太阳神机箱").build();
        System.out.println(asusComputer);
    }
}
